package com.example.pcl.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.pcl.constant.JwtClaimsConstant;
import com.example.pcl.constant.MessageConstants;
import com.example.pcl.exception.ObjectException;
import com.example.pcl.mapper.StudentsMapper;
import com.example.pcl.mapper.UsersMapper;
import com.example.pcl.pojo.dto.StudentQueryDto;
import com.example.pcl.pojo.entity.Appointments;
import com.example.pcl.pojo.entity.ConsultationRecords;
import com.example.pcl.pojo.entity.Students;
import com.example.pcl.pojo.entity.Users;
import com.example.pcl.result.PageResult;
import com.example.pcl.service.IAppointmentsService;
import com.example.pcl.service.IConsultationRecordsService;
import com.example.pcl.service.IStudentsService;
import com.example.pcl.service.IUsersService;
import com.example.pcl.utils.Util;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 学生表，存储学生个人信息，包括学号，年级和学院 服务实现类
 * </p>
 *
 * @author xx
 * @since 2024-12-17
 */
@Service
@RequiredArgsConstructor
public class StudentsServiceImpl extends ServiceImpl<StudentsMapper, Students> implements IStudentsService {


    private final IAppointmentsService appointmentsService;
    private final IConsultationRecordsService recordsService;
    private final UsersMapper usersMapper;

    /**
     * 分页查询学生数据
     *
     * @param queryDto dto
     * @return 分页后的数据
     */
    @Override
    public PageResult<?> pageList(@NotNull StudentQueryDto queryDto) {
        String name = queryDto.getName();
        String grade = queryDto.getGrade();
        String college = queryDto.getCollege();
        String major = queryDto.getMajor();
        String studentNumber = queryDto.getStudentNumber();
        Page<Students> studentsPage = baseMapper.selectPage(new Page<>(queryDto.getPageNum(), queryDto.getPageSize()), new LambdaUpdateWrapper<Students>()
                .like(StringUtils.isNotBlank(name), Students::getName, name)
                .like(StringUtils.isNotBlank(grade), Students::getGrade, grade)
                .like(StringUtils.isNotBlank(major), Students::getMajor, major)
                .like(StringUtils.isNotEmpty(studentNumber), Students::getStudentNumber, studentNumber)
                .like(StringUtils.isNotBlank(college), Students::getCollege, college));
        return new PageResult<>(studentsPage.getTotal(), studentsPage.getRecords());
    }

    /**
     * 添加学生
     *
     * @param student 学生实体
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(@NotNull Students student) {
        // 插入用户信息
        Users user = Users.builder()
                .role(Users.STUDENT) // 设置角色为学生
                .accountStatus(Users.NORMAL) // 设置账号状态正常
                .username(student.getStudentNumber()) // 使用学号作为用户名
                .password(Util.encryptPassword(JwtClaimsConstant.INITIAL_PASSWORD)) // 加密初始密码
                .build();

        int insert = usersMapper.insert(user);

        // 验证用户创建结果
        if (insert <= 0) {
            throw new ObjectException("用户信息创建失败，无法继续添加学生！");
        }

        // 关联用户 ID 并插入学生信息
        student.setUserId(user.getUserId());
        boolean addStudent = save(student);

        // 验证学生信息保存结果
        if (!addStudent) {
            throw new ObjectException("学生信息保存失败！");
        }
    }


    /**
     * 批量导入学生信息（Excel 文件）
     *
     * @param students 上传的 Excel 文件解析后的学生列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addBatch(List<Students> students) {
        // 检查输入是否为空
        if (CollectionUtil.isEmpty(students)) {
            throw new ObjectException(MessageConstants.STUDENT_LIST_NULL);
        }

        // 提取上传的学号列表并确保传入数据中学号唯一
        List<String> uploadStudentNumbers = students.stream()
                .map(Students::getStudentNumber)
                .distinct()
                .toList();

        // 查询数据库中已存在的学号
        List<String> existingStudentNumbers = listObjs(new LambdaQueryWrapper<Students>()
                .select(Students::getStudentNumber)
                .in(Students::getStudentNumber, uploadStudentNumbers));

        // 如果存在重复的学号，抛出异常
        if (CollectionUtil.isNotEmpty(existingStudentNumbers)) {
            throw new ObjectException(
                    String.format("以下学号已存在，无法重复添加: %s", String.join(", ", existingStudentNumbers)));
        }

        // 为每个学生生成对应的用户信息并绑定
        for (Students student : students) {
            Users user = Users.builder()
                    .role(Users.STUDENT)
                    .accountStatus(Users.NORMAL)
                    .username(student.getStudentNumber())
                    .password(Util.encryptPassword(JwtClaimsConstant.INITIAL_PASSWORD))
                    .build();

            // 插入用户信息并获取生成的 userId
            int insert = usersMapper.insert(user);
            if (insert <= 0) {
                throw new ObjectException("用户创建失败，无法绑定到学生！");
            }

            // 设置学生的 userId
            student.setUserId(user.getUserId());
        }

        // 保存学生列表到数据库
        boolean saveResult = saveBatch(students);
        if (!saveResult) {
            throw new ObjectException(MessageConstants.ADD_ERR);
        }
    }

    /**
     * 批量删除学生信息
     *
     * @param studentIds 学生 ID 列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBatch(List<Integer> studentIds) {
        // 1. 检查传入的学生 ID 列表是否为空
        if (CollectionUtil.isEmpty(studentIds)) {
            throw new ObjectException(MessageConstants.DELETE_LIST_NULL);
        }

        // 2. 查询学生对应的用户 ID 列表
        List<Students> students = list(new LambdaQueryWrapper<Students>()
                .in(Students::getStudentId, studentIds)
                .isNotNull(Students::getUserId));

        if (CollectionUtil.isEmpty(students)) {
            throw new ObjectException("未找到对应的学生信息！");
        }

        List<Integer> userIds = students.stream()
                .map(Students::getUserId)
                .distinct()
                .toList();

        // 3. 检查用户是否存在未完成的预约记录
        List<Appointments> pendingAppointments = appointmentsService.list(new LambdaQueryWrapper<Appointments>()
                .in(Appointments::getUserId, userIds)
                .in(Appointments::getStatus, Arrays.asList(Appointments.TO_BE_CONFIRMED, Appointments.CONFIRMED))); // 状态为待确认或已确认

        if (CollectionUtil.isNotEmpty(pendingAppointments)) {
            String userIdWithPending = pendingAppointments.stream()
                    .map(appointment -> appointment.getUserId().toString())
                    .distinct()
                    .collect(Collectors.joining(", "));
            throw new ObjectException(
                    String.format("以下用户存在未完成的预约记录，无法删除: %s", userIdWithPending));
        }

        // 4. 删除用户对应的访谈记录
        List<Integer> appointmentIds = appointmentsService.list(new LambdaQueryWrapper<Appointments>()
                        .in(Appointments::getUserId, userIds))
                .stream()
                .map(Appointments::getAppointmentId)
                .toList();

        if (CollectionUtil.isNotEmpty(appointmentIds)) {
            recordsService.remove(new LambdaQueryWrapper<ConsultationRecords>()
                    .in(ConsultationRecords::getAppointmentId, appointmentIds));
        }

        // 5. 删除用户的预约记录
        appointmentsService.remove(new LambdaQueryWrapper<Appointments>()
                .in(Appointments::getUserId, userIds));
        // 6. 删除学生信息
        boolean deleteStudentsResult = removeBatchByIds(studentIds);
        if (!deleteStudentsResult) {
            throw new ObjectException(MessageConstants.DELETE_ERR);
        }

        // 7. 删除用户信息
        int deleteUsersResult = usersMapper.deleteBatchIds(userIds);
        if (deleteUsersResult <= 0) {
            throw new ObjectException("删除用户信息失败！");
        }


    }

    /**
     * 导出学生信息
     *
     * @return 导出的 Excel 文件字节流
     */
    @Override
    public ByteArrayOutputStream exportStudents() {
        // 查询所有学生信息
        List<Students> studentsList = list();

        if (CollectionUtil.isEmpty(studentsList)) {
            throw new ObjectException("暂无学生信息可导出");
        }

        // 创建 Excel 文件
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("学生信息");

        // 设置表头
        String[] headers = {"学号", "姓名", "年级", "学院", "专业"};
        Row headerRow = sheet.createRow(0);
        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
        }

        // 填充学生信息
        for (int i = 0; i < studentsList.size(); i++) {
            Students student = studentsList.get(i);
            Row row = sheet.createRow(i + 1);
            row.createCell(0).setCellValue(student.getStudentNumber());
            row.createCell(1).setCellValue(student.getName());
            row.createCell(2).setCellValue(student.getGrade());
            row.createCell(3).setCellValue(student.getCollege());
            row.createCell(4).setCellValue(student.getMajor());
        }

        // 写入到输出流
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            workbook.write(outputStream);
            workbook.close();
            return outputStream;
        } catch (IOException e) {
            e.printStackTrace(); // 打印堆栈信息
            throw new ObjectException("导出学生信息失败");
        }
    }


}
